﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Emgu.CV;
using Emgu.CV.Structure;
using System.Drawing;
using System.Windows.Threading;
using System.ComponentModel;
using OxyPlot;
using System.IO;
using OxyPlot.Wpf;


namespace CiliaryDetector
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 
    public struct AngleAndFrame
    {
        public double angle;
        public double Frmae;
    }
    public partial class MainWindow : Window
    {
        //for UI
        public SliderToTextBoxBinding obj1;
        private double TotalFrames;
        private double framenumber;
        private double fps;

        private readonly OxyPlot.LineSeries redLine;
        private PlotModel pm;
       
        private int counter1 = -1;
        private int c;
        private int d;

        private List<double> angles;
       
        private Capture _Capture;
        private string openedfile;
        private bool isFirstTime;
        private bool isRoiEnabled;
        private bool isRoiApplied;
        private bool isShowOpticalFlow = true;

        private double errorstan;

        public Image<Bgr, Byte> firstFrame{ get; set; }
        public Image<Gray, Byte> PrevGrayFrame { get; set; }
        public Image<Bgr, Byte> nextFrame { get; set; }
        public Image<Gray, Byte> nextGrayFrame { get; set; }
        
        public Image<Bgr, Byte> RoiFrame { get; set; }
        public Image<Bgr, Byte> RoinextFrame { get; set; }
        public Image<Gray, Byte> RoiGrayFrame { get; set; }
        public Image<Gray, Byte> RoinextGrayFrame { get; set; }

        public Image<Bgr, Byte> opticalFlowFrame { get; set; }

        public double QualityLevel { get; set; }
        public int MaxFeaturePerChannel { get; set; }
        public double Speed { get; set; }
      
        public List<Image<Bgr, byte>> imgList;
        public List<AngleAndFrame> anglelist;
        private int _MaxFeaturePerChannel = 400;
        private double _qualityLevel = 0.01;
        private double _Speed;
        private double angle;
        private double sumangle = 0;
        private int maxdistance;
        
        //For test!
        private List<string> strbutter = new List<string>();
        private List<double> logdata = new List<double>();
        private double amp = 0; // amplitude
        
        // for the sake of tracking
        public System.Drawing.Rectangle trackingArea;
        public DispatcherTimer My_Time = new DispatcherTimer();
        public PointF[][] ROIActualFeature;
        public PointF[][] ActualFeature;
       
        public PointF[] NextFeature;
        public Byte[] Status;
        public float[] TrackError;
        //private double TrackSucessRate = 90;
        //private double curTrackSucessRate;

        private System.Windows.Point _mouseDownPosition;
       
        public Image<Bgr, byte> largeFrame;// size of the VideWnd control.
        public System.Windows.Shapes.Rectangle RoiRect;
        public System.Windows.Shapes.Rectangle OldRoiRect = null;
       
        public MainWindow()
        {
            InitializeComponent();
            isFirstTime = true;
            isRoiEnabled = false;
            
            obj1 = new SliderToTextBoxBinding();
            this.DataContext = obj1;

            angles = new List<double>();

            anglelist = new List<AngleAndFrame>();
            imgList = new List<Image<Bgr, byte>>();
            
            My_Time.Interval = System.TimeSpan.FromMilliseconds(100); //deault
            My_Time.Tick += new EventHandler(TimerEvent);

            pm = new PlotModel("CBF Waveform");
          
            redLine = new OxyPlot.LineSeries(OxyColors.Red);
            redLine.Smooth = true;

            pm.Series.Add(redLine);
            pm.PlotMargins = new OxyThickness(60, 0, 0, 30);
          
        }
      
        public void FristGrap(String strfile)
        {
            String temp = strfile;
            _Capture = new Capture(temp);
            firstFrame = _Capture.QueryFrame();
                if (firstFrame != null)
                {
                    VideoWnd.Width = firstFrame.Size.Width;
                    VideoWnd.Height = firstFrame.Size.Height;
                    VideoWnd.Source = BitmapSourceConvert.CreateBitmapSourceFromBitmap(firstFrame.ToBitmap());
                    imgList.Add(firstFrame);
                    btnFeature.IsEnabled = true;
                    btnStart.IsEnabled = false;
                    levelslider.IsEnabled = true;
                    tbQualityLevel.IsEnabled = true;
                 
                    TotalFrames = _Capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
                  
                    pm.Axes.Clear();
                    chart.InvalidatePlot();
                 
                    double LineMax, LineMin, majStep, minStep;
                    int intemp;
                    if (amp <= 0)
                        amp = 500;
                    intemp = (int)Math.Log10(amp);
                    LineMax = Math.Pow(10, intemp+1);
                    LineMin = -1 * Math.Pow(10, intemp+1);
                    majStep = 2 * Math.Pow(10, intemp);
                    minStep = 5 * Math.Pow(10, intemp-1);

                    fps = _Capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS);
                    pm.Axes.Add(new OxyPlot.LinearAxis(AxisPosition.Left, LineMin, LineMax, majStep, minStep, "Amplitude"));
                    pm.Axes.Add(new OxyPlot.LinearAxis(AxisPosition.Bottom, 0, TotalFrames/(int)fps, "Seconds"));
                    chart.Model = pm;
                 
                    lbTotalNumFrame.Content = TotalFrames.ToString();
                  
                    lbFPS.Content = fps.ToString();
                    lbCurNumFrame.Content = "1";

                    PrevGrayFrame = firstFrame.Convert<Gray, Byte>();
                    isRoiApplied = false;
                }
        }

        public void ROIGoodFeaturesTracking(Image<Bgr, byte> frame)
        { 
            if (frame != null)
            {
                Image<Bgr, Byte>  temp1 = new Image<Bgr, Byte>(frame.Size);
                Image<Gray, Byte> temp2 = new Image<Gray, Byte>(frame.Size);
                temp1 = frame.Copy();
                temp2 = temp1.Convert<Gray, Byte>();

                if (_qualityLevel == 0)
                {
                    _qualityLevel = 0.01;
                    MessageBox.Show("Zero cannot be accepted.");
                }
                ActualFeature = temp2.GoodFeaturesToTrack(_MaxFeaturePerChannel, _qualityLevel, 5d, 5);
                temp2.FindCornerSubPix(ActualFeature, new System.Drawing.Size(5, 5), new System.Drawing.Size(-1, -1), new MCvTermCriteria(25, 1.5d));

                for (int i = 0; i < ActualFeature[0].Length; i++)
                {
                    temp1.Draw(new CircleF(new PointF(ActualFeature[0][i].X, ActualFeature[0][i].Y), 1f), new Bgr(System.Drawing.Color.Red), 1);
                }
                VideoWnd.Source = BitmapSourceConvert.CreateBitmapSourceFromBitmap(temp1.ToBitmap());
            }
        }
        public String OpenFile()
        {
            string filename = "";
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            
            // Set filter for file extension and default file extension 
            dlg.DefaultExt = ".avi";
            dlg.Filter = "Video files (.avi)|*.avi";

            // Display OpenFileDialog by calling ShowDialog method 
            Nullable<bool> result = dlg.ShowDialog();
            // Get the selected file name.
            if (result == true)
            {
                filename = dlg.FileName;
                imgList.Clear();
                btnStart.IsEnabled = true;
                btnRun.IsEnabled = false;
                tbFPC.IsEnabled = true;
                return filename;
            }
            else
                return filename;
        }

        private void btnOpen_Click(object sender, RoutedEventArgs e)
        {
            redLine.Points.Clear();
            openedfile = OpenFile();
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            if (!String.IsNullOrEmpty(openedfile) || !String.IsNullOrWhiteSpace(openedfile))
            {
                FristGrap(openedfile);
            }
        }

        private void RootImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!isRoiEnabled)
                return;

            if (imgList.Count >= 2)
            {
                MessageBox.Show("Please use the ROI funtion only one time! ");
                return;
            }

            _mouseDownPosition = e.GetPosition(sender as UIElement);
           
            RoiRect = new System.Windows.Shapes.Rectangle
            {
                Stroke = System.Windows.Media.Brushes.Red,
                StrokeThickness = 2,
                Fill = System.Windows.Media.Brushes.Transparent
            };
            Canvas.SetLeft(RoiRect, _mouseDownPosition.X);
            Canvas.SetTop(RoiRect, _mouseDownPosition.X);
            RootImage.Children.Add(RoiRect);
            isFirstTime = false;
        }

        private void RootImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (!isRoiEnabled)
                return;

            if (e.LeftButton == MouseButtonState.Released && RoiRect != null)
            {
                RoiFrame = new Image<Bgr, Byte>(trackingArea.Width, trackingArea.Height);
                maxdistance = Isqrt((int)Power(trackingArea.Width, 2) + (int)Power(trackingArea.Height, 2));
                firstFrame.ROI = trackingArea;
                firstFrame.Copy(RoiFrame, null);
                firstFrame.ROI = System.Drawing.Rectangle.Empty;
                PrevGrayFrame = RoiFrame.Convert<Gray, Byte>();
                List<PointF> tempPointFL = new List<PointF>();
                int j = 0;
                ROIActualFeature = new PointF[1][];
                for (int i = 0; i < ActualFeature[0].Length; i++)
                {    
                    if (trackingArea.Contains((int)ActualFeature[0][i].X, (int)ActualFeature[0][i].Y))
                    {
                        j++;
                        ActualFeature[0][i].X -= trackingArea.X;
                        ActualFeature[0][i].Y -= trackingArea.Y;
                        tempPointFL.Add(new PointF(ActualFeature[0][i].X, ActualFeature[0][i].Y));
                    }
                }
                ROIActualFeature[0] = new PointF[j];
                for (int k = 0; k < j; k++)
                {
                    ROIActualFeature[0][k].X = tempPointFL[k].X;
                    ROIActualFeature[0][k].Y = tempPointFL[k].Y;

                    RoiFrame.Draw(new CircleF(new PointF(ROIActualFeature[0][k].X, ROIActualFeature[0][k].Y), 1f), new Bgr(System.Drawing.Color.Green), 1);
                }

                imgList.Add(RoiFrame);
                ActualFeature[0] = ROIActualFeature[0];
                VideoWnd.Source = BitmapSourceConvert.CreateBitmapSourceFromBitmap(RoiFrame.ToBitmap());
                isRoiApplied = true;
                if (!isFirstTime && RootImage.Children.Count > 1)
                {
                    RootImage.Children.RemoveAt(1);
                }

                RoiRect = null;
            }
        }

        private void RootImage_MouseMove(object sender, MouseEventArgs e)
        {
            if (!isRoiEnabled)
                return;
            if (e.LeftButton == MouseButtonState.Released || RoiRect == null)
                return;

            var pos = e.GetPosition(RootImage);

            var x = Math.Min(pos.X, _mouseDownPosition.X);
            var y = Math.Min(pos.Y, _mouseDownPosition.Y);

            var w = Math.Max(pos.X, _mouseDownPosition.X) - x;
            var h = Math.Max(pos.Y, _mouseDownPosition.Y) - y;

            RoiRect.Width = w;
            RoiRect.Height = h;

            Canvas.SetLeft(RoiRect, x);
            Canvas.SetTop(RoiRect, y);

            trackingArea = new System.Drawing.Rectangle((int)_mouseDownPosition.X, (int)_mouseDownPosition.Y, (int)RoiRect.Width, (int)RoiRect.Height);
        }

        private void btnFeature_Click(object sender, RoutedEventArgs e)
        {
            bool stringok2 = int.TryParse(tbFPC.Text, out _MaxFeaturePerChannel);
            if (stringok2)
            {
                MaxFeaturePerChannel = _MaxFeaturePerChannel;
            }

          ROIGoodFeaturesTracking(firstFrame);
          btnRun.IsEnabled = true;
          tbSpeed.IsEnabled = true;
          tbRoi.Text = "ROI is Enable.";
          isRoiEnabled = true;
         
        }
      
        private void TimerEvent(object sender, System.EventArgs e)
        {
            if (!String.IsNullOrEmpty(openedfile) || !String.IsNullOrWhiteSpace(openedfile))
            {
                    StringBuilder sb = new StringBuilder();
                    nextFrame = _Capture.QueryFrame();
                    if (nextFrame == null &&  PrevGrayFrame != null)
                    {
                        My_Time.Stop();
                        string curData = System.DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss");
                       
                        DirectoryInfo dir = new DirectoryInfo(@"C:\logfiles");
                        if (dir.Exists == false)
                        {
                            dir.Create();
                        }
                        using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\logfiles\"+curData+".txt"))
                        {
                            foreach (string s in strbutter)
                            {
                                file.WriteLine(s);
                                file.WriteLine(System.Environment.NewLine);
                            }
                        }
                        using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\logfiles\"+"rawData"+curData+".txt"))
                        {
                            foreach (var s in angles)
                            {
                                file.WriteLine(s.ToString());
                                //file.WriteLine(System.Environment.NewLine);
                            }
                        }
                        DirectoryInfo dir1 = new DirectoryInfo(@"C:\ResultImages");
                        if (dir1.Exists == false)
                        {
                            dir1.Create();
                        }

                        //using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                        //{
                            var bitmap = PngExporter.ExportToBitmap(pm, (int)chart.ActualWidth, (int)chart.ActualHeight, OxyColor.FromRgb(255,255,255));
                            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                            encoder.Frames.Add(BitmapFrame.Create(bitmap));

                            using (var filestream = new FileStream(@"C:\ResultImages\" + curData + ".jpg", FileMode.Create))
                                encoder.Save(filestream);

                            //BmpBitmapEncoder enc = new BmpBitmapEncoder();
                            //enc.Frames.Add(BitmapFrame.Create(bitmap));
                            //using (System.IO.FileStream fs = System.IO.File.OpenWrite(@"C:\ResultImages"+curData+".bmp"))
                            //{
                            //    enc.Save(fs);
                            //}
                       // }

                        //var bitmap = PngExporter.ExportToBitmap(
                        //this.Model, (int)this.Plot.ActualWidth, (int)this.Plot.ActualHeight, this.Model.Background);
                        //Clipboard.SetImage(bitmap);

                        _Capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES, 0);
                        VideoWnd.Source = BitmapSourceConvert.CreateBitmapSourceFromBitmap(firstFrame.ToBitmap());
                        btnRun.IsEnabled = false;
                        btnStop.IsEnabled = false;
                        btnReset.IsEnabled = true;
                      
                        return;
                    }

                    if (isRoiApplied)
                    {
                        if (trackingArea != null)
                            nextFrame.ROI = trackingArea;
                        nextFrame.Copy(RoiFrame, null);
                        nextGrayFrame = RoiFrame.Convert<Gray, Byte>();

                        opticalFlowFrame = new Image<Bgr, Byte>(RoiFrame.Width, RoiFrame.Height);
                        opticalFlowFrame = nextFrame.Copy();
                    }
                    else
                    {
                        nextGrayFrame = nextFrame.Convert<Gray, Byte>();
                        opticalFlowFrame = new Image<Bgr, Byte>(nextFrame.Width, nextFrame.Height);
                        opticalFlowFrame = nextFrame.Copy();
                    }

                    OpticalFlow.PyrLK(PrevGrayFrame, nextGrayFrame, ActualFeature[0], new System.Drawing.Size(10, 10), 5, new MCvTermCriteria(10, 0.03d), out NextFeature, out Status, out TrackError);
                    double a = 0;
                    double errorcounter = 0;
                    for (int i = 0; i < ActualFeature[0].Length; i++)
                    {
                        if (DrawFlowVectors(i) == false)
                            errorcounter++;
                        sb.Append(angle.ToString());
                        sb.Append(System.Environment.NewLine);
                        a += angle;
                    }
                    strbutter.Add(sb.ToString());
                    counter1++;
                    angles.Add(a);
                    double per; //error rate
                    if (errorcounter == 0)
                        per = 100;
                    else if (ActualFeature[0].Length == 0)
                        per = 0;
                    else
                        per = (double)(errorcounter / ActualFeature[0].Length) * 100;
                    if (per <= errorstan)
                        ActualFeature[0] = NextFeature;    
                    else
                        ActualFeature = nextFrame.GoodFeaturesToTrack(_MaxFeaturePerChannel, _qualityLevel, 5d, 5);
                    //ActualFeature = nextFrame.GoodFeaturesToTrack(_MaxFeaturePerChannel, _qualityLevel, 5d, 5);
                    PrevGrayFrame = nextGrayFrame;
                    VideoWnd.Source = BitmapSourceConvert.CreateBitmapSourceFromBitmap(opticalFlowFrame.Convert<Gray,Byte>().ToBitmap());
                    framenumber = _Capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
                    lbCurNumFrame.Content = framenumber.ToString();

                    sumangle = 0;
                    double ang1 = 0;
                    double ang2 = 0;
                    if (angles.Count >= 2)
                    {
                        ang1 = angles[counter1 - 1];
                        ang2 = angles[counter1];
                        if (ang1 >= 0)
                            c = 1;
                        else
                            c = 0;
                        if (ang2 >= 0)
                            d = 1;
                        else
                            d = 0;
                        }
                        if (amp <= 0)
                            amp = 500;
                        if (c == 1 && d == 0)
                            sumangle = amp;
                        else if (c == 0 && d == 1)
                            sumangle = -amp;

                        redLine.Points.Add(new DataPoint(framenumber / (int)fps, sumangle));
                        chart.InvalidatePlot();
            }
        }

        private bool DrawFlowVectors(int i)
        {
            System.Drawing.Point p = new System.Drawing.Point();
            System.Drawing.Point q = new System.Drawing.Point();
            p.X = (int)ActualFeature[0][i].X;
            p.Y = (int)ActualFeature[0][i].Y;
            q.X = (int)NextFeature[i].X;
            q.Y = (int)NextFeature[i].Y;

            double distance = Isqrt((int)Power(p.X-q.X, 2) + (int)Power(p.Y-q.Y, 2));
            if (distance <= 3 || distance >= maxdistance)
                return false;
            if (distance == 0)
                return false;
            angle = Math.Atan2((double)p.Y - q.Y, (double)p.X - q.X);
            if (isShowOpticalFlow)
            {
                LineSegment2D line = new LineSegment2D(p, q);
                opticalFlowFrame.Draw(line, new Bgr(255, 255, 255), 1);
                p.X = (int)(q.X + 6 * Math.Cos(angle + Math.PI / 4));
                p.Y = (int)(q.Y + 6 * Math.Sin(angle + Math.PI / 4));
                opticalFlowFrame.Draw(new LineSegment2D(p, q), new Bgr(255, 255, 255), 1);
                p.X = (int)(q.X + 6 * Math.Cos(angle - Math.PI / 4));
                p.Y = (int)(q.Y + 6 * Math.Sin(angle - Math.PI / 4));
                opticalFlowFrame.Draw(new LineSegment2D(p, q), new Bgr(255, 255, 255), 1);
            }
            return true;
        }

        private void btnRun_Click(object sender, RoutedEventArgs e)
        {
            bool stringok1 = double.TryParse(tbQualityLevel.Text, out _qualityLevel);
            if (stringok1)
            {
                QualityLevel = _qualityLevel;
            }

            bool stringok3 = double.TryParse(tbSpeed.Text, out _Speed);
            if (stringok3)
            {
                Speed = _Speed;
                My_Time.Interval = System.TimeSpan.FromMilliseconds(Speed);
            }

            if (My_Time != null)
            {
                My_Time.Start();
                btnRun.IsEnabled = false;
                tbSpeed.IsEnabled = false;
                btnOpen.IsEnabled = false;
                btnStop.IsEnabled = true;
                btnFeature.IsEnabled = false;
                levelslider.IsEnabled = false;
                tbQualityLevel.IsEnabled = false;
                tbRoi.Text = "ROI is Disable.";
                isRoiEnabled = false;
                tbFPC.IsEnabled = false;
                btnReset.IsEnabled = false;
                tbAmp.IsEnabled = false;
                senseslider.IsEnabled = false;
                tbErrorSen.IsEnabled = false;
            }
        }
  
        private PointF FindCentroid(PointF[] Hull)
        {
            int num_points = Hull.Length;
            PointF[] pts = new PointF[num_points + 1];
            Hull.CopyTo(pts, 0);
            pts[num_points] = Hull[0];
            float X = 0;
            float Y = 0;
            float second_factor;
            for (int i = 0; i < num_points; i++)
            {
                second_factor = pts[i].X * pts[i + 1].Y - pts[i + 1].X * pts[i].Y;
                X += (pts[i].X + pts[i + 1].X) * second_factor;
                Y += (pts[i].Y + pts[i + 1].Y) * second_factor;
            }
            float polygon_area = Math.Abs(SignedPolygonArea(Hull));
            X /= (6 * polygon_area);
            Y /= (6 * polygon_area);
            if (X < 0)
            {
                X = -X;
                Y = -Y;
            }
            return new PointF(X, Y);
        }

        private float SignedPolygonArea(PointF[] Hull)
        {
            int num_points = Hull.Length;
            float area = 0;
            for (int i = 0; i < num_points; i++)
            {
                area +=
                    (Hull[(i + 1) % num_points].X - Hull[i].X) *
                    (Hull[(i + 1) % num_points].Y + Hull[i].Y) / 2;
            }
            return area;
        }

        private void DrawTrackedFeatures(int i)
        {
            opticalFlowFrame.Draw(new CircleF(new PointF(ActualFeature[0][i].X, ActualFeature[0][i].Y), 1f), new Bgr(System.Drawing.Color.Blue), 1);
        }

        private void VideoWnd_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!isRoiEnabled)
                return;
            if (imgList.Count > 1)
            {
                imgList.Remove(imgList.Last());
                VideoWnd.Source = BitmapSourceConvert.CreateBitmapSourceFromBitmap(imgList.Last().ToBitmap());
                isRoiApplied = false;
                PrevGrayFrame = firstFrame.Convert<Gray, Byte>();
            }
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            if (My_Time != null)
            {
                My_Time.Stop();
                btnRun.IsEnabled = true;
                tbSpeed.IsEnabled = true;
                btnStop.IsEnabled = false;
                btnOpen.IsEnabled = true;
                btnReset.IsEnabled = true;
                tbErrorSen.IsEnabled = true;
                senseslider.IsEnabled = true;
            }
        }

        private void tbQualityLevel_TextChanged(object sender, TextChangedEventArgs e)
        { 
            tbQualityLevel.GetBindingExpression(TextBox.TextProperty).UpdateSource();
        }

        private void levelslider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            _qualityLevel = ((double)e.NewValue) / 1000;
        }

        public static int Isqrt(int num)
        {
            if (0 == num) { return 0; }  // Avoid zero divide  
            int n = (num / 2) + 1;       // Initial estimate, never low  
            int n1 = (n + (num / n)) / 2;
            while (n1 < n)
            {
                n = n1;
                n1 = (n + (num / n)) / 2;
            } // end while  
            return n;
        } // end Isqrt()  

        private double Power(double a, int b)
        {
            if (b < 0)
            {
                throw new ApplicationException("B must be a positive integer or zero");
            }
            if (b == 0) return 1;
            if (a == 0) return 0;
            if (b % 2 == 0)
            {
                return Power(a * a, b / 2);
            }
            else if (b % 2 == 1)
            {
                return a * Power(a * a, b / 2);
            }
            return 0;
        }

        private void btnReset_Click(object sender, RoutedEventArgs e)
        {
            btnOpen.IsEnabled = true;
            tbAmp.IsEnabled = true;
            btnFeature.IsEnabled = false;
            tbRoi.Text = "ROI is disable.";
            isRoiEnabled = false;
            isRoiApplied = false;
            btnRun.IsEnabled = false;
            btnStop.IsEnabled = false;
            tbQualityLevel.IsEnabled = false;
            tbFPC.IsEnabled = false;
            chart.InvalidatePlot();
            redLine.Points.Clear();
            VideoWnd.Source = null;
            btnStart.IsEnabled = false;
            _Capture = null;
            imgList.Clear();
            anglelist.Clear();
            firstFrame = null;
            PrevGrayFrame = null;
            nextFrame = null;
            nextGrayFrame = null;
            RoiFrame = null;
            RoinextFrame = null;
            RoiGrayFrame = null;
            RoinextGrayFrame = null;
            opticalFlowFrame = null;
            sumangle = 0;
            ROIActualFeature = null;
            ActualFeature = null;
            NextFeature = null;
            tbFPC.IsEnabled = true;
            tbErrorSen.IsEnabled = true;
            senseslider.IsEnabled = true;
            lbFPS.Content = "";
            lbCurNumFrame.Content = "0";
            lbTotalNumFrame.Content = "0";
          
        }

        private void cbEnableOF_Checked(object sender, RoutedEventArgs e)
        {
            isShowOpticalFlow = false;
        }

        private void cbEnableOF_Unchecked(object sender, RoutedEventArgs e)
        {
            isShowOpticalFlow = true;
        }

        private void tbAmp_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (String.IsNullOrEmpty(tbAmp.Text) || String.IsNullOrWhiteSpace(tbAmp.Text))
            {
                amp = 500;
                return;
            }
            amp = double.Parse(tbAmp.Text);
        }

        private void senseslider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            errorstan = ((double)e.NewValue);
        }

        private void tbErrorSen_TextChanged(object sender, TextChangedEventArgs e)
        {
            tbErrorSen.GetBindingExpression(TextBox.TextProperty).UpdateSource();
        } 
    }

  
}
